/**
 * This file is a part of VideoCut package.
 * ---------------------------------------------------------------------- 
 * Copyright (C) 2007-2008 troorl
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * ---------------------------------------------------------------------- 
 *
 * @author troorl <troorl@gmail.com>
 */

#include "TXine.h"

TXine::TXine()
{
	vo_driver = "auto";
}

int TXine::init(const char *mrl)
{
	xine = xine_new();
	xine_init(xine);
	if((vo_port = xine_open_video_driver(xine, vo_driver, XINE_VISUAL_TYPE_NONE, NULL)) == NULL)
	{
		return CANT_FIND_VIDEO_CODEC;
	}

	stream = xine_stream_new(xine, NULL, vo_port);
	
	if(!xine_open(stream, mrl))
	{
		return CANT_OPEN_FILE;
	}
	
	xine_get_pos_length(stream, 0, 0, &length);
	xine_play(stream, 0, 0);
	
	return 0;
}

const char *TXine::videoCodec()
{
	return xine_get_meta_info(stream, XINE_META_INFO_VIDEOCODEC);
}

const char *TXine::audioCodec()
{
	return xine_get_meta_info(stream, XINE_META_INFO_AUDIOCODEC);
}

int TXine::getLength()
{
	return length;
}

QImage TXine::getCurrentFrame(int frameNumber) const//, int *width, int *height) 
{
	int width, height;
	xine_play(stream, 0, frameNumber);
	
	uint8_t *yuv = NULL, *y = NULL, *u = NULL, *v =NULL ;
	int /*width, height,*/ ratio, format;
	
	if (!xine_get_current_frame(this->stream, &width, &height, &ratio, &format, NULL))
	{
		
	}
	
	yuv = new uint8_t[((width + 8) * (height + 1) * 2)];
	xine_get_current_frame(this->stream, &width, &height, &ratio, &format, yuv);
	y = yuv;
	u = yuv + width * height;
	v = yuv + width * height * 5 / 4;
	
	unsigned char *rgb32BitData = yv12ToRgb(y, u, v, width, height);
	
	QImage screenShot(rgb32BitData, width, height, QImage::Format_RGB32);
	delete [] yuv;
	
	//return rgb32BitData;
	return screenShot;
}

unsigned char *TXine::yv12ToRgb(uint8_t *src_y, uint8_t *src_u, uint8_t *src_v, int width, int height) const
{
#define clip_8_bit(val)              \
	{                                    \
	if (val < 0)                      \
	val = 0;                       \
	else                              \
	if (val > 255) val = 255;      \
}
	
	int     i, j;
	int     y, u, v;
	int     r, g, b;
	int     sub_i_uv;
	int     sub_j_uv;
	
	int     uv_width, uv_height;
	unsigned char *rgb;
	
	uv_width  = width / 2;
	uv_height = height / 2;
	
	rgb = new unsigned char[(width * height * 4)];
	
	if (!rgb)
	{
		return NULL;
	}
	
	for (i = 0; i < height; ++i)
	{
		sub_i_uv = ((i * uv_height) / height);
		
		for (j = 0; j < width; ++j)
		{
			sub_j_uv = ((j * uv_width) / width);
			
			y = src_y[(i * width) + j] - 16;
			u = src_u[(sub_i_uv * uv_width) + sub_j_uv] - 128;
			v = src_v[(sub_i_uv * uv_width) + sub_j_uv] - 128;
			
			r = (int)((1.1644 * (double)y) + (1.5960 * (double)v));
			g = (int)((1.1644 * (double)y) - (0.3918 * (double)u) - (0.8130 * (double)v));
			b = (int)((1.1644 * (double)y) + (2.0172 * (double)u));
			
			clip_8_bit (r);
			clip_8_bit (g);
			clip_8_bit (b);
			
			rgb[(i * width + j) * 4 + 0] = b;
			rgb[(i * width + j) * 4 + 1] = g;
			rgb[(i * width + j) * 4 + 2] = r;
			rgb[(i * width + j) * 4 + 3] = 0;
		}
	}
	
	return rgb;
}

void TXine::close()
{
	// Closing Xine
	xine_close(stream);
	xine_dispose(stream);
	xine_close_video_driver(xine,vo_port);
}
